package com.aaa.mbs.util;

import java.util.UUID;

import com.aaa.mbs.config.MQOrderQueueConfig;
import com.aaa.mbs.entity.LocalMessage;
import com.aaa.mbs.service.LocalMessageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSONObject;


/**
 * fileName:SenderService
 * description:
 * author: LJV
 * createTime:2021/1/22 15:08
 * version:1.0.0
 */
@Component
@Transactional
public class SenderService implements ReturnCallback, ConfirmCallback {

    private final Logger log= LoggerFactory.getLogger(SenderService.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private LocalMessageService localMessageService;

    public void send(String context,String localMessageId){
        System.out.println("Sender发生内容："+context);
        this.rabbitTemplate.setMandatory(true); // 当Mandatory参数设为true时，如果目的不可达，会发送消息给生产者，生产者通过一个回调函数来获取该信息。
        this.rabbitTemplate.setConfirmCallback(this); //确认回调
        this.rabbitTemplate.setReturnCallback(this);//失败回调
        CorrelationData correlationData=new CorrelationData(localMessageId);//用于确认之后更改本地消息状态或删除--本地消息id
        this.rabbitTemplate.convertAndSend(MQOrderQueueConfig.ORDER_EXCHANGE_NAME,MQOrderQueueConfig.ORDER_ROUTING_KEY,context,correlationData);
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String localMessageId=correlationData.getId();
        // 消息发送成功,更新本地消息为已成功发送状态或者直接删除该本地消息记录,剩余的由MQ投递到消费者端，消费者端需要进行幂等，避免产生脏数据
        if(ack){
            LocalMessage message=new LocalMessage();
            message.setId(Integer.valueOf(localMessageId));
            message.setState(LocalMessage.L_M_STATE_SUCCESS);
            localMessageService.update(message);
        }else{
            //失败处理
            System.out.println("消息发送失败！");
        }
    }

    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.out.println("return--message:" + new String(message.getBody()) + ",replyCode:" + replyCode
                + ",replyText:" + replyText + ",exchange:" + exchange + ",routingKey:" + routingKey);
    }

}
